﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Web.Script.Serialization;
using System.Web;

namespace MVCPlugin.Utility
{
    public class PluginMetadata : IComparable
    {
        private static ILogger Logger = new ConsoleLogger();

        public string UniqueName { get; set; }

        public string DisplayName { get; set; }

        public string Description { get; set; }

        public string Author { get; set; }

        public string ProjectFileName { get; set; }

        public string PluginVersion { get; set; }

        public string RequiredMinAppVersion { get; set; }

        public string MvcControllerNamespace { get; set; }

        [ScriptIgnore]
        internal string EntryAssemblyFileName
        {
            get
            {
                var projectFileDescriptor = GetProjectFileDescriptor();
                if (projectFileDescriptor == null)
                {
                    return null;
                }
                return projectFileDescriptor.AssemblyName + ".dll";
            }
        }

        [ScriptIgnore]
        internal string OutputAbsolutePath
        {
            get
            {
                var projectFileDescriptor = GetProjectFileDescriptor();
                if (projectFileDescriptor == null)
                {
                    return null;
                }
                return projectFileDescriptor.OutputAbsolutePath;
            }
        }

        [ScriptIgnore]
        public PluginStatus Status
        {
            get
            {
                return GetPluginStatus(UniqueName);
            }
        }

        internal bool CheckCompatible()
        {
            PluginMetadata metadata = this;
            Version requiredMinAppVersion;
            try
            {
                requiredMinAppVersion = new Version(metadata.RequiredMinAppVersion);
            }
            catch (Exception ex)
            {
                requiredMinAppVersion = new Version("1.0");
                Logger.Error(ex);
            }

            bool compatible = true;
            return compatible;
        }

        internal Version GetVersion()
        {
            Version v;
            try
            {
                v = new Version(this.PluginVersion);
            }
            catch (Exception ex)
            {
                v = new Version("1.0");
                Logger.Error(ex);
            }
            return v;
        }

        private static PluginStatus GetPluginStatus(string pluginUniqueName)
        {
            string statusFile = Plugin.GetPluginStatusFilePath(pluginUniqueName);
            if (File.Exists(statusFile) == false)
            {
                return PluginStatus.JustDeployed;
            }
            string txt = CacheHelper.GetWithLocalCache<string>(statusFile, () =>
            {
                return File.ReadAllText(statusFile);
            }, statusFile);
            if (string.IsNullOrWhiteSpace(txt))
            {
                return PluginStatus.JustDeployed;
            }
            txt = txt.Trim();
            if (txt == "0")
            {
                return PluginStatus.ToInstall;
            }
            if (txt == "1")
            {
                return PluginStatus.Installed;
            }
            if (txt == "2")
            {
                return PluginStatus.ToUninstall;
            }
            return PluginStatus.JustDeployed;
        }

        private ProjectFileDescriptor GetProjectFileDescriptor()
        {
            string name = this.ProjectFileName;
            if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(UniqueName))
            {
                return null;
            }
            name = name.ToLower().Trim();
            if (name.EndsWith(".csproj") == false)
            {
                name = name + ".csproj";
            }
            string projectFile = Path.Combine(Plugin.GetPluginFolder(this.UniqueName), name);
            return CacheHelper.GetWithLocalCache<ProjectFileDescriptor>(projectFile, () => ProjectFileParser.Parse(projectFile), projectFile);
        }

        public int CompareTo(object obj)
        {
            PluginMetadata m = obj as PluginMetadata;
            if (m == null)
            {
                return 1;
            }
            if (this.UniqueName == null)
            {
                return -1;
            }
            return this.UniqueName.CompareTo(m.UniqueName);
        }
    }
}
